#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>

using namespace std;

// 1. 初始化关键字
map<string, string> keywordMap = {
    {"main", "MAINTK"},
    {"const", "CONSTTK"},
    {"int", "INTTK"},
    {"break", "BREAKTK"},
    {"continue", "CONTINUETK"},
    {"if", "IFTK"},
    {"else", "ELSETK"},
    {"while", "WHILETK"},
    {"getint", "GETINTTK"},
    {"printf", "PRINTFTK"},
    {"return", "RETURNTK"},
    // 逻辑运算符
    {"!", "NOT"},
    {"&&", "AND"},
    {"||", "OR"},
    // 算术运算符
    {"+", "PLUS"},
    {"-", "MINU"},
    {"*", "MULT"},
    {"/", "DIV"},
    {"%", "MOD"},
    // 比较运算符
    {"<", "LSS"},
    {"<=", "LEQ"},
    {">", "GRE"},
    {">=", "GEQ"},
    {"==", "EQL"},
    {"!=", "NEQ"},
    // 赋值运算符
    {"=", "ASSIGN"},
    // 界符
    {";", "SEMICN"},
    {",", "COMMA"},
    {"(", "LPARENT"},
    {")", "RPARENT"},
    {"[", "LBRACK"},
    {"]", "RBRACK"},
    {"{", "LBRACE"},
    {"}", "RBRACE"},
    // 字符串
    {"\"", "STRCON"},
    // 数字常量
    {"INTCON", "INTCON"},
    // 字符常量
    {"void", "VOIDTK"}
};

// 2. 读取文件数据
string readInputFile(const string& filename) {
    ifstream inFile(filename);
    if (!inFile) {
        cerr << "错误：不能打开文件" << filename << endl;
        exit(1);
    }
    cout << "文件打开正常，正在读取数据" << endl;
    string data((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>());
    inFile.close();
    cout << "数据读取成功" << endl;
    return data;
}

// 3. 判断单词类别
bool isNumber(char c) {
    return (c >= '0' && c <= '9');
}

bool isUnder(char c) {
    return (c == '_');
}

bool isLetter(char c) {
    return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}

bool isDoubleSymbol(char c) {
    return (c == '<' || c == '>' || c == '=' || c == '!' || c == '&' || c == '|');
}

bool isSimpleSymbol(char c) {
    return (c == '+' ||  c == '-' || c == '*' || c == '/' || c == '%' || c == ';' || c == ',' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}');
}

bool isStr(char c) {
    return (c == '"');
}

string judgeKind(const string& str) {
    if (keywordMap.count(str)) {
        return keywordMap[str];
    } else {
        return "IDENFR";
    }
}

// 4. 分词
void wordDivision(vector<string>& data, vector<string>& data2, const string& str) {
    int n = str.length();
    for (int i = 0; i < n; i++) {
        string temp;
        string temp2;

        if (str[i] == '/') {
            if (str[i + 1] == '/') { // 单行注释
                while (str[i] != '\n') i++;
            } else if (str[i + 1] == '*') { // 多行注释
                while (!(str[i] == '*' && str[i + 1] == '/')) i++;
                i += 2;
            }
        }

        if (isSimpleSymbol(str[i])) { // 判断是否为单一运算符
            temp = str[i];
            temp2 = temp;
        }
        
        if (isDoubleSymbol(str[i])) { // 判断是否可为双个运算符
            temp += str[i];
            if (isDoubleSymbol(str[i + 1])) {
                temp += str[i + 1];
                i++;
            }
            temp2 = temp;
        }

        if (isStr(str[i])) { // 判断是否为字符串 (STRCON)
            temp2 += str[i];
            i++;
            while (!isStr(str[i])) {
                temp2 += str[i];
                i++;
            }
            temp2 += str[i];
            temp = "\"";
        }

        if (isNumber(str[i])) { // 判断是否为数字常量 (INTCON)
            temp = "INTCON";
            temp2 += str[i];
            i++;
            while (isNumber(str[i])) {
                temp2 += str[i];
                i++;
            }
            i--;
        }

        if (isLetter(str[i]) || isUnder(str[i])) { // 判断是否为字母或下划线 (IDENFR)
            temp += str[i];
            i++;
            while (isLetter(str[i]) || isNumber(str[i]) || isUnder(str[i])) {
                temp += str[i];
                i++;
            }
            i--;
            temp2 = temp;
        }

        if (!temp.empty()) {
            data.push_back(judgeKind(temp));
            data2.push_back(temp2);
        }
    }
}

// 5. 输出结果
void outputResult(const vector<string>& data, const vector<string>& data2, const string& filename) {
    ofstream outFile(filename);
    if (!outFile) {
        cerr << "错误：不能打开文件" << filename << endl;
        exit(1);
    }
    for (int i = 0; i < data.size(); i++) {
        outFile << data[i] << " " << data2[i] << endl;
    }
    outFile.close();
    cout << "结果成功输出" << endl;
}

int main() {
    string filename = "testfile.txt";
    string str = readInputFile(filename);
    vector<string> data;
    vector<string> data2;
    wordDivision(data, data2, str);
    outputResult(data, data2, "output.txt");
    return 0;
}